﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using AutoMoq;
using EnvDTE;
using Microsoft.VisualStudio.TextTemplating;
using Moq;

namespace SmartStringResources.Tests
{
	public abstract class AResourceFileInNeutralEnvironment : AResourceFile
	{
		protected object _host;
		protected string _resourceFileName;
		protected string _templateFileName;
		protected IFileSystemService _fileSystemService;
		protected AutoMoqer _autoMoqer;
		protected StringWriter _stringWriter;
		protected ProjectItemsImpl _projectItems;
		protected Mock<ProjectItem> _resourceProjectItem;
		protected Mock<ProjectItem> _templateProjectItem;
		protected PropertiesImpl _resourceProjectItemProperties;

		protected override void Context()
		{
			base.Context();

			_autoMoqer = new AutoMoqer();

			var hostMock = new Mock<IServiceProvider>();
			var engineHostMock = hostMock.As<ITextTemplatingEngineHost>();

			_autoMoqer.SetInstance(engineHostMock.Object);
			_autoMoqer.SetInstance(hostMock.Object);
			_host = engineHostMock.Object;

			_autoMoqer.GetMock<DTE>()
				.DefaultValue = DefaultValue.Mock;

			hostMock
				.Setup(p => p.GetService(It.Is<Type>(t => t == typeof(DTE))))
				.Returns(_autoMoqer.GetMock<DTE>().Object);

			_stringWriter = new StringWriter();
			_autoMoqer.GetMock<IFileSystemService>()
				.Setup(service => service.GetStreamWriter(It.IsAny<string>(), It.IsAny<FileMode>()))
				.Returns(_stringWriter);

			_autoMoqer.GetMock<IFileSystemService>()
				.Setup(service => service.OpenFileStream(It.IsAny<string>()))
				.Returns((string path) => new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read));

			_autoMoqer.GetMock<IFileSystemService>()
				.Setup(service => service.Exists(It.Is<string>(s => s == _resourceFileName)))
				.Returns(true);

			_fileSystemService = _autoMoqer.GetMock<IFileSystemService>().Object;

			_resourceFileName = ResourceFileName;
			_templateFileName = Path.ChangeExtension(_resourceFileName, "tt");

			_resourceProjectItem = new Mock<ProjectItem>();

			_resourceProjectItem
				.Setup(pi => pi.FileCount)
				.Returns(1);

			_resourceProjectItem
				.Setup(pi => pi.get_FileNames(It.Is<short>(s => s == 0)))
				.Returns(_resourceFileName);

			_resourceProjectItemProperties = new PropertiesImpl();
			_resourceProjectItem
				.Setup(pi => pi.Properties)
				.Returns(_resourceProjectItemProperties);

			_templateProjectItem = new Mock<ProjectItem>();

			_templateProjectItem
				.Setup(pi => pi.FileCount)
				.Returns(1);

			_templateProjectItem
				.Setup(pi => pi.get_FileNames(It.Is<short>(s => s == 0)))
				.Returns(_templateFileName);

			_templateProjectItem
				.Setup(pi => pi.ProjectItems)
				.Returns(new ProjectItemsImpl());

			_projectItems = new ProjectItemsImpl { _templateProjectItem.Object, _resourceProjectItem.Object };
			_autoMoqer.GetMock<DTE>()
				.Setup(dte => dte.ActiveDocument.ProjectItem.ContainingProject.ProjectItems)
				.Returns(_projectItems);
		}
	}
}
